*
* $Id$
*
* $Log: gnsphr.F,v $
* Revision 1.1.1.1  2002/06/16 15:18:39  hristov
* Separate distribution  of Geant3
*
* Revision 1.1.1.1  1999/05/18 15:55:17  fca
* AliRoot sources
*
* Revision 1.3  1996/03/28 08:50:23  cernlib
* In the call to function MAX  use NULL istead of 0. to get the proper
* type of argument.
*
* Revision 1.2  1996/02/27 10:12:06  ravndal
* Precision problem (neg. Sqrt) solved
*
* Revision 1.1.1.1  1995/10/24 10:20:54  cernlib
* Geant
*
*
#include "geant321/pilot.h"
*CMZ :  3.21/02 29/03/94  15.41.30  by  S.Giani
*-- Author :
      SUBROUTINE GNSPHR (X, PAR, IACT, SNEXT, SNXT, SAFE)
C.
C.    ******************************************************************
C.    *                                                                *
C.    *       COMPUTE DISTANCE UP TO INTERSECTION WITH 'SPHE' VOLUME,  *
C.    *       FROM INSIDE POINT X(1-3) ALONG DIRECTION X(4-6)          *
C.    *                                                                *
C.    *       PAR   (input)  : volume parameters                       *
C.    *       IACT  (input)  : action flag                             *
C.    *         = 0  Compute SAFE only                                 *
C.    *         = 1  Compute SAFE, and SNXT only if SNEXT .GT.new SAFE *
C.    *         = 2  Compute both SAFE and SNXT                        *
C.    *         = 3  Compute SNXT only                                 *
C.    *       SNEXT (input)  : see IACT = 1                            *
C.    *       SNXT  (output) : distance to volume boundary             *
C.    *       SAFE  (output) : shortest distance to any boundary       *
C.    *                                                                *
C.    *    ==>Called by : GNEXT, GTNEXT                                *
C.    *         Author  A.McPherson,  P.Weidhaas  *********            *
C.    *                                                                *
C.    ******************************************************************
C.
#if !defined(CERNLIB_SINGLE)
      IMPLICIT DOUBLE PRECISION (A-H,O-Z)
#endif
#include "geant321/gconsp.inc"
      REAL X(6), PAR(6), SNXT, SNEXT, SAFE
      PARAMETER (ZERO=0,ONE=1,SMALL=ONE/BIG)
 
C---------------------------------------------------------------
 
      SNXT = BIG
      R2   = X(1)*X(1) + X(2)*X(2) + X(3)*X(3)
      R    = SQRT (R2)
      RIN  = PAR(1)
      ROUT = PAR(2)
      SAF1 = R - RIN
      SAF2 = ROUT - R
 
      IF (IACT .LT. 3) THEN
 
C       -------------------------------------------------
C       |  Compute safety-distance 'SAFE' (P.Weidhaas)  |
C       -------------------------------------------------
 
         SAFE = MIN (SAF1, SAF2)
         IF( RIN .EQ. 0.0 ) THEN
            SAFE = ROUT-R
            SAF3 = SAFE
            SAF4 = SAFE
         ELSE
            SAF3 = R
            SAF4 = R
         ENDIF
         IF( R .GT. 1.E-5) THEN
            IF( PAR(4)-PAR(3).GE.180.) THEN
               SAF3 = BIG
            ELSE
               TH = ACOS(X(3)/SNGL(R))*RADDEG
               IF (TH.LT.0) TH = 180.+TH
               DTH1 = TH-PAR(3)
               DTH2 = PAR(4)-TH
               DTH = MIN(DTH1,DTH2)
               SAF3 = R*SIN(DTH*DEGRAD)
            ENDIF
            RXY2 = X(1)*X(1)+X(2)*X(2)
            IF( RXY2 .GT. 1.E-12.AND. PAR(6)-PAR(5) .LT. 360) THEN
               RXY = SQRT(RXY2)
               PHI=ATAN2(X(2),X(1))*RADDEG
               DPH = PHI-PAR(5)
               SG = SIGN(ONE,DPH)
               DPH = MOD( ABS(DPH), ONE*360 )
               IF(SG.LE.0.) DPH = 360.-DPH
               DPHT = PAR(6)-PAR(5)
               IF(DPHT .LT. 0.) DPHT = DPHT+360.
               DDPH = MIN(DPH,DPHT-DPH)
               IF( DDPH .GT. 90.) THEN
                  SAF4 = BIG
               ELSE
                  SAF4 = RXY*SIN(DDPH*DEGRAD)
               ENDIF
            ENDIF
         ENDIF
         SAFE = MIN(ONE*SAFE,SAF3,SAF4)
 
         IF (IACT .EQ. 0) GO TO 999
         IF (IACT .EQ. 1) THEN
            IF (SNEXT .LT. SAFE) GO TO 999
         ENDIF
      ENDIF
 
C     ------------------------------------------------
C     |  Compute vector-distance 'SNXT' (McPherson)  |
C     ------------------------------------------------
 
      IF(R.LT.1.0E-5) GO TO 70
 
      C1=(X(1)*X(4)+X(2)*X(5)+X(3)*X(6)) / R
      RTMP = PAR(2)
      SGN=ONE
      AC=R*R * (ONE-C1*C1)
      IF(AC.GT.PAR(1)**2.OR.C1.GT.0.0) GO TO 10
      SGN=-ONE
      RTMP = PAR(1)
   10 CONTINUE
      RTMPAC=MAX(RTMP*RTMP-AC,ZERO)
      SNXT=SQRT(RTMPAC)*SGN-R*C1
      DPSGN=X(1)*X(5)-X(2)*X(4)
      PHI2=PAR(6)
      IF(DPSGN.LT.0.0) PHI2=PAR(5)
C
      TSGN=SIN(PHI2*DEGRAD)
      TCSG=COS(PHI2*DEGRAD)
      DEN=X(4)*TSGN-X(5)*TCSG
      IF(DEN.EQ.0.0) GO TO 20
      SP=(X(2)*TCSG-X(1)*TSGN)/DEN
      IF(SP.LT.0.0) GO TO 20
      IF(ABS(TSGN).GT.1.E-6.AND.(X(2)+SP*X(5))*TSGN
     +       .LT.0.)GO TO 20
      IF(ABS(TCSG).GT.1.E-6.AND.(X(1)+SP*X(4))*TCSG
     +       .LT.0.)GO TO 20
C
      IF(SP.LT.SNXT) SNXT=SP
C
   20 CONTINUE
C
      TH2=PAR(4)
      IBOUN=0
   30 CONTINUE
      IBOUN=IBOUN+1
C
      STH=SIN(TH2*DEGRAD)
      CTH=COS(TH2*DEGRAD)
      STH2=STH*STH
      CTH2=CTH*CTH
      AA=STH2*X(6)**2-CTH2*(X(4)**2+X(5)**2)
      BB=STH2*X(6)*X(3)-CTH2*(X(4)*X(1)+
     +X(5)*X(2))
      CC=STH2*X(3)**2-CTH2*(X(1)**2+X(2)**2)
      SQ=BB*BB-AA*CC
      IF(SQ.LT.0.0) GO TO 60
      ST=BIG
      IF(ABS(BB).GE.SMALL) ST=-CC*0.5/BB
      ITRY=1
      IF(AA.EQ.0.0) GO TO 45
      T2=SQRT(SQ)/AA
      ITRY=0
      T1=-BB/AA
   40 CONTINUE
      ST=T1+T2
   45 CONTINUE
      IF((X(3)+ST*X(6))*CTH.LT.0.0) GO TO 50
      IF(ST.GT.0.0.AND.ST.LT.SNXT) SNXT=ST
   50 CONTINUE
      IF(ITRY.NE.0) GO TO 60
      ITRY=1
      T2=-T2
      GO TO 40
   60 CONTINUE
      IF(IBOUN.NE.1) GO TO 999
      TH2=PAR(3)
      GO TO 30
C
   70 CONTINUE
C              THIS BIT FOR X,Y,Z=0,0,0
C
      SNXT=PAR(2)
C              WE HAVE IGNORED THETA AND PHI BUT USERS SHOULDN'T
C              USE THETA PHI SEGMENTATION AT R=0 ANYWAY.
C
  999 CONTINUE
      END
